﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using System.IO;

namespace GenerateWorkItem
{

    enum TestEnum
    {
        Lasse,
        Liten,
        Blues
    };

    public partial class Form1 : Form
    {
        private ManagementPackClass SelectedClass;
        private ManagementPack SelectedMp;
        private string managementPackName = "";
        internal EnterpriseManagementGroup mg = new EnterpriseManagementGroup("spisrv6");
        private StringBuilder finalClass = new StringBuilder();
        private TestEnum triaf;
        public Form1()
        {
            InitializeComponent();

            //Incident test = new Incident(mg);
            //test.Commit();
            //Add management pack classes
            foreach (var item in AllManagementPacks)
            {
                this.comboBox_mp.Items.Add(item);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void comboBox_mp_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.comboBox_classes.Items.Clear();

            SelectedMp = null;
            if (this.comboBox_mp.SelectedItem is ManagementPack)
            {
                SelectedMp = this.comboBox_mp.SelectedItem as ManagementPack;

                foreach (var item in SelectedMp.GetClasses())
                {
                    this.comboBox_classes.Items.Add(item);
                }



            }


        }




        private void button1_Click(object sender, EventArgs e)
        {
            if (this.comboBox_classes.SelectedItem is ManagementPackClass)
            {
                SelectedClass = this.comboBox_classes.SelectedItem as ManagementPackClass;
                className = SelectedClass.DisplayName;
                finalClass = new StringBuilder();

                buildUsingBlock();
                // buildEnums();
                buildClassInit();
                buildConstructor();
                buildSetupManagementsPacks();
                buildCommit();
                buildProperties();
                buildRelationships();
                buildEndBlock();
                writeClass();

                MessageBox.Show("Done!");

            }
        }

        private void writeClass()
        {
            StreamWriter sw = File.CreateText(@"C:\Users\oleks\Documents\Visual Studio 2008\Projects\TestWorkItems\TestWorkItems\" + className + ".cs");
            string toWrite = finalClass.ToString();
            sw.Write(toWrite);

            sw.Close();

        }

        private string className = "";

        private void buildUsingBlock()
        {
            string temp = "using System;using System.Collections.Generic;using System.Linq;using System.Web;using Microsoft.EnterpriseManagement;using Microsoft.EnterpriseManagement.Common;using Microsoft.EnterpriseManagement.Configuration.IO;using Microsoft.EnterpriseManagement.Configuration;using System.IO;using System.Text;";
            foreach (string s in temp.Split(';'))
            {
                if (s.Length > 0)
                    finalClass.AppendLine(s + ";");
            }
            finalClass.AppendLine("");
        }

        private void buildClassInit()
        {
            finalClass.AppendLine("");
            finalClass.AppendLine("public class " + className);
            finalClass.AppendLine("{");
            finalClass.AppendLine("private EnterpriseManagementGroup mg;");
            finalClass.AppendLine("private ManagementPackClass " + className + "Class;");
            finalClass.AppendLine("private EnterpriseManagementObjectProjection " + className + "Projection;");
            finalClass.AppendLine("");
            finalClass.AppendLine("// Management pack references");
            finalClass.AppendLine("private ManagementPack systemMp;");
            finalClass.AppendLine("private ManagementPack " + managementPackName + "Mp;");
        }

        private void buildConstructor()
        {
            finalClass.AppendLine("");
            finalClass.AppendLine("public " + className + "(EnterpriseManagementGroup managementGroup)");
            finalClass.AppendLine("{");
            finalClass.AppendLine("SetupManagementPacks(managementGroup);");
            finalClass.AppendLine("string ID = \"" + className + "{0}\";");
            finalClass.AppendLine(className + "Projection.Object[" + className + "Class, \"Id\"].Value = ID;");
            finalClass.AppendLine("}");
            ////        this.changeRequestProjection.Object[this.changeRequestClass, "Id"].Value = crID;
        }

        private void buildSetupManagementsPacks()
        {
            finalClass.AppendLine("");
            finalClass.AppendLine("private void SetupManagementPacks(EnterpriseManagementGroup managementGroup)");
            finalClass.AppendLine("{");
            finalClass.AppendLine("mg = managementGroup;");
            finalClass.AppendLine("systemMp = mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);");
            finalClass.AppendLine("Version version = systemMp.Version;");
            finalClass.AppendLine("string keyToken = systemMp.KeyToken;");
            finalClass.AppendLine("systemMp = mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);");
            finalClass.AppendLine(managementPackName + "Mp = mg.ManagementPacks.GetManagementPack(new Guid(\"" + SelectedMp.Id + "\"));");
            finalClass.AppendLine("systemMp = mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);");
            finalClass.AppendLine(className + "Class = this.mg.EntityTypes.GetClass(new Guid(\"" + SelectedClass.Id + "\"));");
            finalClass.AppendLine(className + "Projection = new EnterpriseManagementObjectProjection(mg, " + className + "Class);");
            finalClass.AppendLine("}");
            finalClass.AppendLine("");
        }

        private void buildCommit()
        {
            finalClass.AppendLine(" public void Commit()");
            finalClass.AppendLine("{");
            finalClass.AppendLine(className + "Projection.Commit();");
            finalClass.AppendLine("}");
        }

        private void buildEndBlock()
        {
            finalClass.AppendLine("}");

        }

        private void buildRelationships()
        {
            foreach (var item in SelectedClass.GetBaseTypes())
            {
                ManagementPackClass current = item.GetManagementPack().GetClass(item.Name);
                foreach (var relation in current.GetRelationshipsWhereSource())
                {
                    finalClass.AppendLine("public void Add" + relation.Source.Name + "(EnterpriseManagementObject target)");
                    finalClass.AppendLine("{");
                    finalClass.AppendLine(" ManagementPackRelationship relation = this.mg.EntityTypes.GetRelationshipClass(\"" + relation.Name +  "\", this.Mp);");
                    finalClass.AppendLine(className + "Projection.Add(target, relation.Target);");
                    finalClass.AppendLine(className + "Projection.Overwrite();"); 
                    finalClass.AppendLine("}");
                    finalClass.AppendLine("");

                }
            }
        }

     
        //public void SetAssignedUser(EnterpriseManagementObject assignedUser)
        //{
        //    ManagementPackRelationship assignedTo = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemAssignedToUser", this.Mp);
  
        //    this.IncidentProjection.Add(assignedUser, assignedTo.Target);

        //    this.IncidentProjection.Overwrite();
        //}

        //    try
        //    {
        //        this.IncidentProjection[assignedTo.Target][0].Remove();
        //    }
        //    catch (ArgumentOutOfRangeException)
        //    {
        //        // No one was previously assigned the incident.
        //    }

        private List<ManagementPack> allManagementPacks = null;
        private List<ManagementPack> AllManagementPacks
        {
            get
            {
                if (allManagementPacks == null)
                    allManagementPacks = mg.ManagementPacks.GetManagementPacks().ToList<ManagementPack>();
                return allManagementPacks;
            }

        }

        private void buildEnums()
        {
            List<string> addedEnums = new List<string>();
            foreach (var item in SelectedClass.GetProperties())
            {
                if (item.Type == ManagementPackEntityPropertyTypes.@enum)
                {
                    ManagementPackEnumeration mu = item.EnumType.GetElement();
                    if (addedEnums.Contains(mu.Name))
                        continue;
                    addedEnums.Add(mu.Name);
                    StringBuilder temp = new StringBuilder();
                    temp.AppendLine("public enum " + mu.Name);
                    temp.AppendLine("{");
                    bool foundOne = false;

                    List<string> addedValues = new List<string>();

                    foreach (ManagementPack mp in AllManagementPacks)
                    {
                        foreach (var enumeration in mp.GetEnumerations())
                        {
                            if (enumeration.Name.StartsWith(mu.Name + "."))
                            {
                                string enumValue = enumeration.Name.Substring(enumeration.Name.IndexOf('.') + 1);
                                if (addedValues.Contains(enumValue))
                                    continue;
                                addedValues.Add(enumValue);
                                temp.AppendLine(enumValue.Replace('.', '_') + ",");
                                foundOne = true;
                            }
                        }
                    }

                    temp.AppendLine("}");
                    if (foundOne)
                        finalClass.AppendLine(temp.ToString());

                    SelectedMp.GetEnumerations();
                }
            }
        }

        private void buildProperties()
        {
            foreach (var item in SelectedClass.GetProperties(BaseClassTraversalDepth.Recursive, PropertyExtensionMode.All))
            {
                string name = item.Name;
                string type = item.Type.ToString();

                if (type == "enum")
                {
                    ManagementPackEnumeration mu = item.EnumType.GetElement();
                    finalClass.AppendLine("public " + mu.Name.Replace('.', '_') + " " + name);
                    finalClass.AppendLine("{");
                    finalClass.AppendLine("set");

                    finalClass.AppendLine("{");
                    finalClass.AppendLine("ManagementPack enumMp = " + className + "Projection.Object[" + className + "Class, \"" + name + "\"].Type.GetManagementPack();");
                    finalClass.AppendLine("ManagementPackElementCollection<ManagementPackEnumeration> enums = enumMp.GetEnumerations();");
                    finalClass.AppendLine("ManagementPackEnumeration enumValue = enums.GetItem(\"" + mu.Name + ".\" + value.ToString());");
                    finalClass.AppendLine(className + "Projection.Object[" + className + "Class, \"" + name + "\"].Value = enumValue.Id;");
                    finalClass.AppendLine("}");
                    finalClass.AppendLine("}");
                }
                else
                {
                    type = fixType(type);
                    finalClass.AppendLine("public " + type + " " + name);
                    finalClass.AppendLine("{");
                    finalClass.AppendLine("get");
                    finalClass.AppendLine("{");
                    if (type.ToLower() == "string")
                        finalClass.AppendLine("return " + className + "Projection.Object[" + className + "Class, \"" + name + "\"].Value.ToString();");
                    else
                        finalClass.AppendLine("return " + type + ".Parse(" + className + "Projection.Object[" + className + "Class, \"" + name + "\"].Value.ToString());");
                    finalClass.AppendLine("}");
                    finalClass.AppendLine("set");
                    finalClass.AppendLine("{");
                    finalClass.AppendLine(className + "Projection.Object[" + className + "Class, \"" + name + "\"].Value = value;");
                    finalClass.AppendLine("}");
                    finalClass.AppendLine("}");
                }

            }
        }

        //    public int Priority
        //    {
        //        get { return int.Parse(this.changeRequestProjection.Object[this.changeRequestClass, "Priority"].Value.ToString()); }
        //        set { this.changeRequestProjection.Object[this.changeRequestClass, "Priority"].Value = value; }
        //    }

        //ManagementPack enumMp = this.incidentProjection.Object[this.incidentClass, "Impact"].Type.GetManagementPack();
        //       ManagementPackElementCollection<ManagementPackEnumeration> enums = enumMp.GetEnumerations();
        //       ManagementPackEnumeration lowImpactEnum = enums.GetItem("System.WorkItem.TroubleTicket.ImpactEnum.Low");
        //       this.incidentProjection.Object[this.incidentClass, "Impact"].Value = lowImpactEnum.Id;



        private string fixType(string type)
        {
            string result = "";
            type = type.ToLower();

            switch (type)
            {
                case "datetime":
                    result = "DateTime";
                    break;
                case "bool":
                    result = "Boolean";
                    break;
                case "enum":

                default:
                    break;
            }

            if (type.ToLower() == "datetime")
                result = "DateTime";
            else
                result = type;
            return result;

        }

        private void button2_Click(object sender, EventArgs e)
        {
            GenerateHelpClass newClass = new GenerateHelpClass(mg, textBox1.Text);
        }

    }
}





//    public string Description
//    {
//        get { return this.changeRequestProjection.Object[this.changeRequestClass, "Description"].Value.ToString(); }
//        set { this.changeRequestProjection.Object[this.changeRequestClass, "Description"].Value = value; }
//    }

//    public string DisplayName
//    {
//        get { return this.changeRequestProjection.Object[this.changeRequestClass, "DisplayName"].Value.ToString(); }
//        set { this.changeRequestProjection.Object[this.changeRequestClass, "DisplayName"].Value = value; }
//    }
//    public string Id
//    {
//        get { return this.changeRequestProjection.Object[this.changeRequestClass, "Id"].Value.ToString(); }
//    }


//    /// <summary>
//    /// Sets the user that the incident is assigned to.
//    /// </summary>
//    public void SetAssignedUser(EnterpriseManagementObject assignedUser)
//    {
//        ManagementPackRelationship assignedTo = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemAssignedToUser", this.workItemMp);

//        // Remove the previously assigned user if there is one.
//        try
//        {
//            this.changeRequestProjection[assignedTo.Target][0].Remove();
//        }
//        catch (ArgumentOutOfRangeException)
//        {
//            // No one was previously assigned the incident.
//        }

//        // Assign the incident to the user.
//        this.changeRequestProjection.Add(assignedUser, assignedTo.Target);

//        this.Overwrite();
//    }


//    public void Overwrite()
//    {
//        this.changeRequestProjection.Overwrite();
//    }


//    /// <summary>
//    /// Creates user criteria xml.
//    /// </summary>
//    private static string CreateUserCriteriaXml(EnterpriseManagementGroup mg, string username)
//    {
//        ManagementPack mpWindows = mg.ManagementPacks.GetManagementPack(SystemManagementPack.Windows);

//        // This is XML that validates against the Microsoft.EnterpriseManagement.Core.Criteria schema.                  
//        string userCriteria = String.Format(@"
//                <Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
//                   <Expression>
//                    <SimpleExpression>
//                      <ValueExpressionLeft>
//                        <Property>$Target/Property[Type='Microsoft.AD.User']/DistinguishedName$</Property>
//                      </ValueExpressionLeft>
//                      <Operator>Equal</Operator>
//                      <ValueExpressionRight>
//                        <Value>contoso\{2}</Value>
//                      </ValueExpressionRight>
//                    </SimpleExpression>
//                  </Expression>
//                </Criteria>
//                ", mpWindows.KeyToken, mpWindows.Version.ToString(), username);

//        return userCriteria;
//    }

//}

//public class ChangeRequest
//{
//    private EnterpriseManagementGroup mg;
//    private ManagementPackClass changeRequestClass;
//    private EnterpriseManagementObjectProjection changeRequestProjection;

//    // Management pack references
//    private ManagementPack systemMp;
//    private ManagementPack workItemMp;
//    private ManagementPack changeRequestManagementMp;
//    private ManagementPack changeRequestConfigurationMp;
//    private ManagementPack ateaSpintopMP;
//    private ManagementPack smCoreMp;
//    private ManagementPack activityMp; 

//    //Constants
//    private const string ServiceManager_ChangeRequestManagement_Library = "System.WorkItem.ChangeRequest.Library";
//    private const string ServiceManager_ChangeManagement_Configuration = "ServiceManager.ChangeManagement.Configuration";
//    private const string AteaSpintop = "Spintop.Services";
//    private const string SM_Core = "ServiceManager.Core.Library";
//    private const string SM_WorkItem = "System.WorkItem.Library";
//    private const string CreateFolderActivity = "Spintop.Activities.CreateSharedFolder";
//    private const string ActivityMP = "System.WorkItem.Activity.Library";

//    /// <summary>
//    /// Creates a new Change Request
//    /// </summary>
//    public ChangeRequest(EnterpriseManagementGroup managementGroup)
//    {
//        SetupManagementPacks(managementGroup);

//        this.SetupIncident(assignedUser, affectedUser, createdByUser, description, folderName);
//    }


//    private void SetupManagementPacks(EnterpriseManagementGroup managementGroup)
//    {
//        this.mg = managementGroup;
//        this.systemMp = this.mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);
//        Version version = systemMp.Version;
//        string keyToken = systemMp.KeyToken;

//        this.changeRequestManagementMp = this.mg.ManagementPacks.GetManagementPack(ServiceManager_ChangeRequestManagement_Library, keyToken, version);
//        this.changeRequestConfigurationMp = this.mg.ManagementPacks.GetManagementPack(ServiceManager_ChangeManagement_Configuration, null, version);
//        this.ateaSpintopMP = this.mg.ManagementPacks.GetManagementPack(AteaSpintop, null, new Version("1.0.0.8"));
//        this.smCoreMp = this.mg.ManagementPacks.GetManagementPack(SM_Core, keyToken, version);
//        this.workItemMp = this.mg.ManagementPacks.GetManagementPack(SM_WorkItem, keyToken, version);
//        this.changeRequestClass = this.mg.EntityTypes.GetClass("System.WorkItem.ChangeRequest", this.changeRequestManagementMp);
//        this.createSharedFolderClass = this.mg.EntityTypes.GetClass(CreateFolderActivity, this.ateaSpintopMP);
//        this.changeRequestProjection = new EnterpriseManagementObjectProjection(this.mg, this.changeRequestClass);
//        this.activityMp = this.mg.ManagementPacks.GetManagementPack(ActivityMP, keyToken, version);
//        this.activityClass = this.mg.EntityTypes.GetClass(CreateFolderActivity, this.ateaSpintopMP);
//    }
//    /// <summary>
//    /// Sets the default property values for the incident.
//    /// </summary>
//    private void SetupIncident(EnterpriseManagementObject assignedUser,
//        EnterpriseManagementObject affectedUser, EnterpriseManagementObject createdByUser,string description, string folderName)
//    {

//        string crID = "CR{0}";

//        this.changeRequestProjection.Object[this.changeRequestClass, "Id"].Value = crID;
//        this.Description = description;
//        // Set the assigned to user.
//        ManagementPackRelationship assignedTo = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemAssignedToUser", this.workItemMp);
//        changeRequestProjection.Add(assignedUser, assignedTo.Target);

//        // Set the affected user.
//        ManagementPackRelationship createdFor = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemAffectedUser", this.workItemMp);
//        changeRequestProjection.Add(affectedUser, createdFor.Target);

//        // Set the created by user.
//        ManagementPackRelationship createdBy = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemCreatedByUser", this.workItemMp);
//        changeRequestProjection.Add(createdByUser, createdBy.Target);

//        ManagementPackRelationship workContains = this.mg.EntityTypes.GetRelationshipClass("System.WorkItemContainsActivity", this.activityMp);
//        changeRequestProjection[workContains.Target][0].Object[activityClass, "FolderName"].Value = folderName;
//        this.Commit();
//    }
//    public void Commit()
//    {
//        this.changeRequestProjection.Commit();
//    }